package com.studiofortress.sf.graphics.display;

import javax.swing.JFrame;

import java.awt.DisplayMode;
import java.awt.GraphicsEnvironment;
import java.awt.Image;

/**
 * The GraphicsFrame class is the standard way of creating a graphics window.
 * 
 * By default this cannot be resized, but it can be enabled. Flickering may
 * occur as the component is resized.
 * 
 * @author Joseph Lenton
 * @version 26/12/2008
 */
public class GraphicsFrame extends GraphicsWrapper<JFrame>
{
    public static final String DEFAULT_TITLE = "";
    public static final boolean DEFAULT_EXIT_ON_CLOSE = true;

    /**
     * This creates a new JFrame using the common setup code required.
     * @param title The title for the JFrame.
     * @param exitOnClose true if the frame should end the JVM when the frame closes, false if not.
     * @return
     */
    private static JFrame newJFrame(String title, boolean exitOnClose)
    {
        if (title == null) {
            throw new IllegalArgumentException("The given title cannot be null.");
        }

        final JFrame newFrame = new JFrame();

        newFrame.setTitle(title);
        if (exitOnClose) {
            newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }


        // ### this section might need to be placed _after_ the call to super
        newFrame.setResizable(false);
        newFrame.setLocationByPlatform(true);
        newFrame.setIgnoreRepaint(true);
        newFrame.setResizable(false);

        return newFrame;
    }

    public GraphicsFrame(int width, int height)
    {
        this(width, height, DEFAULT_TITLE, DEFAULT_EXIT_ON_CLOSE);
    }

    public GraphicsFrame(int width, int height, String title)
    {
        this(width, height, title, DEFAULT_EXIT_ON_CLOSE);
    }

    public GraphicsFrame(int width, int height, boolean exitOnClose)
    {
        this(width, height, DEFAULT_TITLE, exitOnClose);
    }

    /**
     * This class is not meant to be implimented,
     * and is simply to create the workings for all
     * of the various types of Graphic Windows.
     */
    public GraphicsFrame(int width, int height, String title, boolean exitOnClose)
    {
        super(newJFrame(title, exitOnClose), width, height);
    }

    /**
     * This runs the display code for showing this GraphicsFrame. Any subclass
     * of GraphicsFrame should call this once to display this component.
     *
     * This is typically intended to allow a subclass to run certain pieces of
     * code _before_ this has been associated with a display device.
     *
     * All following calls should use setVisible.
     */
    public void display()
    {
        final JFrame frame = getContainer();

        // ensure the frame has been attached to a display device
        frame.addNotify();
        
        // create the control object

        frame.pack();
        frame.setVisible(true);

        DisplayMode display = GraphicsEnvironment.
                getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
        final int screenWidth = display.getWidth();
        final int screenHeight = display.getHeight();
        
        frame.setLocation(
                (screenWidth - getWidth())/2,
                screenHeight < getHeight() ? 0 : (screenHeight - getHeight())/2);

        getCanvas().requestFocus();
    }

    /**
     * @param image The image to appear as the icon for this frame.
     */
    public void setIconImage(Image image)
    {
        getContainer().setIconImage(image);
    }

    /**
     * @return The image currently in use as the icon for this Frame.
     */
    public Image getIconImage()
    {
        return getContainer().getIconImage();
    }

    /**
     * Closes the Graphics Window,
     * and disposes of it's components.
     * This should always be called before
     * exiting the application.
     * 
     * You should not be calling drawing methods
     * on a Graphics Window that has been closed.
     * It may have unexpected results or raise exceptions.
     */
    public void close()
    {
        getContainer().dispose();
    }
}